import java.awt.geom.Point2D;
import java.io.*;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.lang.Math;
import java.util.Random;



public class Bus{
	
	
	ArrayList<Point2D.Double> route;
	double busSpeed; //dist per step period, in coord units
	int stops; //how many steps between stops
	int wait; //how many steps to wait at stop
	String id;
	double x;
	double y;
	int nextTargetPoint; //point in route currently driving to;
	Random rand;
	int stopOffset; //random number (up to half number of steps between stops) added to stop counter so buses dont all stop at same time
	int state; //bus is state machine.  0 = driving, 1+ = stopped at stop
	int stopCount; //counts num of steps stopped picking up and steps driving
	String routeNum;
	
	
	
	public Bus( String id , String routefile , String rn ){
				
		routeNum = rn;
		state = 0;
		stopCount = 0;
		rand = new Random();
		route = new ArrayList<Point2D.Double>();
		busSpeed = 0.0001;
		stops = 12; //60
		wait = 3; //30
		stopOffset = rand.nextInt(stops/2);
		this.id = id;
		nextTargetPoint = 1; //start buss at point 0
		
				
		loadRoute( routefile );
		
		x = route.get(0).getX();
		y = route.get(0).getY();
		
				
	}//cstrcr
	
	
	
	
	
	
	
	public void step(){
		
		switch (state) {
		
			case 0:{//driving
				double distance = 0;
				Point2D.Double target = route.get( nextTargetPoint );
				double distToTarget = target.distance( x , y );
				
				if (distToTarget < busSpeed){ //split by point			
					x = target.getX();		
					y = target.getY();	
					distance = busSpeed - distToTarget;			
					nextTargetPoint++;
					if (nextTargetPoint >= route.size()){
						nextTargetPoint = 0;
					}			
					target = route.get( nextTargetPoint );
					distToTarget = target.distance( x , y );
				}
				else{ //normal, not split by point
					distance = busSpeed;
				}
				
				//alternative location calc: get distance from her to target, calculate what percentage will need to move, then increase x and y by that percentage
				
				double angle = Math.asin(   ( target.getX()-x ) / distToTarget   );
				double angle2 = Math.acos(   ( target.getY()-y ) / distToTarget   );
						
				x += Math.sin(angle) * distance;
				y += Math.cos(angle2) * distance;
				
				stopCount++;
				if ( (stopCount+stopOffset) % stops == 0 ) {
					stopCount = 0;
					state = 1;
				}
			}//case 0 driving
			
			case 1:{//stopped
				stopCount++;
				if (stopCount >= wait){
					stopCount = 0;
					state = 0;
				}
			}//case 1 stopped
		
		}//switch
		
		System.out.println( id + " " + x + " " + y + " " + routeNum );
				
	}//step
	
	
	
	
	public void loadRoute(String routeFile){ //note not tolerant of errors in route file, so dont make any ;)
		
		String line; 

		try {
			BufferedReader br = new BufferedReader(new FileReader( routeFile ));
			while ((line = br.readLine()) != null) { 
								
				StringTokenizer st = new StringTokenizer(line);
				double x =  Double.valueOf( st.nextToken() ).doubleValue();
				double y =  Double.valueOf( st.nextToken() ).doubleValue();
				
				route.add( new Point2D.Double(x,y) );
			
			} 
		}catch(Exception e) {
			System.out.println("Died: " + e);
		}		
		
	}//loadrout
	
	
}
